package com.zrs.gmall.order.receiver;

import com.alibaba.fastjson.JSON;
import com.zrs.gmall.common.constant.MqConst;
import com.zrs.gmall.common.service.RabbitService;
import com.zrs.gmall.enums.model.OrderStatus;
import com.zrs.gmall.enums.model.ProcessStatus;
import com.zrs.gmall.order.model.OrderInfo;
import com.zrs.gmall.order.service.OrderInfoService;
import com.rabbitmq.client.Channel;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.Map;


@Slf4j
@Component
public class OrderReceiver {

    @Autowired
    private OrderInfoService orderInfoService;

    @Autowired
    private RabbitService rabbitService;


    /**
     * 定时关闭订单监听器
     *
     * @param orderId 订单ID
     * @param message
     * @param channel
     */
    @SneakyThrows
    @RabbitListener(queues = {MqConst.QUEUE_ORDER_CANCEL})
    public void closeOrder(Long orderId, Message message, Channel channel) {
        //1.判断消息是否有值
        try {
            if (orderId != null) {
                log.info("[订单微服务],监听关闭订单消息:{}", orderId);
                //2.根据订单ID查询订单对象 判断订单状态
                OrderInfo orderInfo = orderInfoService.getById(orderId);
                if (orderInfo != null && OrderStatus.UNPAID.name().equals(orderInfo.getOrderStatus()) && OrderStatus.UNPAID.name().equals(orderInfo.getProcessStatus())) {
                    //3.修改订单状态
                    orderInfoService.execExpiredOrder(orderId);

                    //4.发送消息到MQ 通知支付系统 关闭本地交易记录
                    rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_PAYMENT_CLOSE, MqConst.ROUTING_PAYMENT_CLOSE, orderId);
                }
                //4.手动应答
                channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
            }
        } catch (IOException e) {
            e.printStackTrace();
            log.error("[订单微服务],关闭订单消息执行异常:", e);
            //希望再次broker再次投递消息
            channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
        }
    }


    /**
     * 监听支付宝支付成功消息
     *
     * @param orderId 订单ID
     * @param message
     * @param channel
     */
    @SneakyThrows
    @RabbitListener(bindings = @QueueBinding(
            exchange = @Exchange(MqConst.EXCHANGE_DIRECT_PAYMENT_PAY),
            value = @Queue(value = MqConst.QUEUE_PAYMENT_PAY, durable = "true"),
            key = MqConst.ROUTING_PAYMENT_PAY
    ))
    public void processPaySuccessMsg(Long orderId, Message message, Channel channel) {
        try {
            if (orderId != null) {
                //处理业务
                log.info("[订单服务]监听支付成功消息:{}", orderId);
                OrderInfo orderInfo = orderInfoService.getById(orderId);
                if (orderInfo != null && !ProcessStatus.PAID.name().equals(orderInfo.getOrderStatus())) {
                    //1.监听到支付成功消息,修改订单状态为已支付
                    orderInfoService.updateOrderStatus(orderId, ProcessStatus.PAID);
                    //2.发送消息到MQ目的通知库存系统库存锁定/扣减
                    orderInfoService.sendDeductStockMsg(orderInfo.getOutTradeNo());
                }
            }
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        } catch (IOException e) {
            e.printStackTrace();
            log.error("[订单服务]处理支付成功消息异常:{}", e);
            channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
        }
    }


    /**
     * 监听库存系统锁定商品库存结果
     *
     * @param deductStr {"orderId":"64","status":"OUT_OF_STOCK"} 或者 {"orderId":"63","status":"DEDUCTED"}
     * @param message
     * @param channel
     */
    @SneakyThrows
    @RabbitListener(bindings = @QueueBinding(
            exchange = @Exchange(MqConst.EXCHANGE_DIRECT_WARE_ORDER),
            value = @Queue(value = MqConst.QUEUE_WARE_ORDER, durable = "true"),
            key = MqConst.ROUTING_WARE_ORDER
    ))
    public void processDeductStockResult(String deductStr, Message message, Channel channel) {
        try {
            if (StringUtils.isNotBlank(deductStr)) {
                log.info("[订单服务],监听库存系统扣减结果:{}", deductStr);
                //根据消息中扣减状态 修改指定订单状态
                Map map = JSON.parseObject(deductStr, Map.class);
                String orderId = (String) map.get("orderId");
                String status = (String) map.get("status");
                if (StringUtils.isNotBlank(orderId) && StringUtils.isNotBlank(status)) {
                    //待发货
                    if ("DEDUCTED".equals(status)) {
                        orderInfoService.updateOrderStatus(Long.valueOf(orderId), ProcessStatus.WAITING_DELEVER);
                    }
                    //库存异常
                    if ("OUT_OF_STOCK".equals(status)) {
                        orderInfoService.updateOrderStatus(Long.valueOf(orderId), ProcessStatus.STOCK_EXCEPTION);
                    }
                }
                channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
            }
        } catch (IOException e) {
            e.printStackTrace();
            channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
        }
    }



}
